require 'net/http'
require 'uri'
require 'thread'

class Release

  def initialize()
    @count = 0
    @mutex = Mutex.new
    @max_threads = 40
  end

  def execute(site)
    threads = []
    releases = site.releases.dup
    request_count = releases.count * 4;
    start = Time.now
    puts "Starting release scan of #{releases.count} releases with up to #{request_count} reqs using #{@max_threads} connections/threads."
    group = releases.pop(@max_threads)
    while not group.nil? and group.count > 0
      (group).each do |release|
        threads << Thread.new {
          analyze_release(release)
        }
      end
      threads.each { |thr| thr.join }
      group = releases.pop(@max_threads)
      threads = []
    end
    duration = Time.now - start
    puts
    puts "Release scan completed in #{duration} seconds."
  end

  def analyze_release(release)
    version = release[:version]
    dl_uri = URI('https://download.jboss.org')
    Net::HTTP.start(dl_uri.host, dl_uri.port, :use_ssl => dl_uri.scheme == 'https') do |http|
      {:zip => '.zip',  :tgz => '.tar.gz', :srczip => '-src.zip', :srctgz => '-src.tar.gz'}.each do |kind, suffix|
        release[kind] = kind_content(http, "https://download.jboss.org/wildfly/#{version}/wildfly-#{version}#{suffix}")
      end
      {:zip => '.zip',  :tgz => '.tar.gz', :srczip => '-src.zip', :srctgz => '-src.tar.gz'}.each do |kind, suffix|
        content = kind_content(http, "https://download.jboss.org/wildfly/#{version}/servlet/wildfly-web-#{version}#{suffix}")
        if (content[:size] != "unknown")
          release[:servlet] = {} unless release.has_key?(:servlet)
          release[:servlet][kind] = content
        end
        content = kind_content(http, "https://download.jboss.org/wildfly/#{version}/servlet/wildfly-servlet-#{version}#{suffix}")
        if (content[:size] != "unknown")
          release[:servlet] = {} unless release.has_key?(:servlet)
          release[:servlet][kind] = content
        end
      end
      if release.has_key?("updateforversion")
        release[:update] = kind_content(http, "https://download.jboss.org/wildfly/#{version}/wildfly-#{version}-update.zip")
      end
      if release.has_key?("updateforversionfull")
        versionfull = release["updateforversionfull"]
        release[:updatefull] = kind_content(http, "https://download.jboss.org/wildfly/#{version}/wildfly-#{version}-#{versionfull}-update.zip")
      end
      if release.has_key?("quickversion")
        version = release[:quickversion] 
        uri = URI.parse("https://download.jboss.org/wildfly/#{version}/quickstart-#{version}.zip")
        release[:quickstart] = {:url => uri, :size => compute_size(http,uri)}
      end
    end
  end

  def kind_content(http, baseuri)
    uri = URI.parse(baseuri)
    size = compute_size(http,uri)
    hashuri = find_hash(http, baseuri)
    if (hashuri.nil?)
      {:url => uri, :size => size}
    elsif (hashuri.path.end_with?("sha1"))
      {:url => uri, :size => size, :hashurl => hashuri, :hashtype => "SHA-1"}
    else
      {:url => uri, :size => size, :hashurl => hashuri, :hashtype => "MD5"}
    end
  end

  def compute_size(http, uri)
    response = http.head( uri.path )
    b = response['content-length'] || ''
    if ( response.code == "200" and ! b.empty? )
      print_wrap 'x'
      formatBytes(b)
    else
      print_wrap '.'
      'unknown'
    end
  end

  def print_wrap(char) 
    @mutex.synchronize {
      if (@count += 1) % @max_threads == 0
        puts char
      else
        print char
      end
    }
  end

  def formatBytes(bytes)
    bytes = bytes.to_f
    units = ["bytes", "KB", "MB", "GB", "TB", "PB"]

    i = 0
    while bytes > 1024 and i < 6 do
      bytes /= 1024
      i += 1
    end

    sprintf("%.0f %s", bytes, units[i])
  end 

  def find_hash(http, baseuri)
    ['sha1', 'md5'].each do |suffix|
      uri = URI.parse("#{baseuri}.#{suffix}")
      response = http.get( uri.path )
      if ( response.code == "200" and response['content-length'] )
        return uri
      end
    end
    nil
  end

end

